package com.xmd.red.utils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import com.thoughtworks.xstream.XStream;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class WxUtil {

	/**
	 * 微信参数签名
	 */
	public static <T> T sign(T t, String key) {

		Class<? extends Object> clazz = t.getClass();
		String signStr = "";
		Field[] fields = clazz.getDeclaredFields();
		List<Field> list = new ArrayList<Field>();
		for (Field field : fields) {
			list.add(field);
		}
		Collections.sort(list, new Comparator<Field>() {

			public int compare(Field o1, Field o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
		try {
			for (Field field : list) {
				String fieldName = field.getName();
				String fieldNametemp = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				Method method = clazz.getMethod(fieldNametemp, new Class[] {});
				Object o = method.invoke(t);
				if (o != null && !fieldName.equals("sign")) {
					signStr += fieldName + "=" + String.valueOf(o) + "&";
				}
			}
			signStr = signStr + "key=" + key;
			// 对签名字符串进行md5加密,并转成大写
			signStr = DigestUtils.md5Hex(signStr).toUpperCase();
			// 调用setSign()方法,把计算出来的签名赋值进去
			Method signMethod = clazz.getMethod("setSign", String.class);
			signMethod.invoke(t, signStr);

		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * 对象转xml
	 */
	public static <T> String toXml(T t) {
		XStream xstream = new XStream();
		xstream.autodetectAnnotations(true);
		String xml = xstream.toXML(t).replace("__", "_");
		return xml;
	}

	/**
	 * xml转对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toObj(String xml, Class<T> clazz) {
		
		if(StringUtils.isEmpty(xml)){
			return null;
		}

		XStream xstream = new XStream();
		xstream.alias("xml", clazz);
		Object obj = null;
		try{
			obj = xstream.fromXML(xml);
		}catch(Exception e){
			System.out.println("xml转object报错");
			e.printStackTrace();
		}
		return (T) obj;
	}

	/**
	 * 把数字转成10位
	 */
	public static String to10Num(int num) {

		String numStr = String.valueOf(num);
		int strLen = numStr.length();
		int leftNum = 10 - strLen;
		for (int i = 0; i < leftNum; i++) {
			numStr = "0" + numStr;
		}
		return numStr;
	}

	/***
	 * 使用okhttp把xml数据封装成流的形式来请求微信接口
	 */
	public static String okPost(String xml, String url,String keyUrl,String password) {

		String result = null;
		MediaType mediaType = MediaType.parse("text/xml");
		
		//东楚风证书
		//String filePath = "d:/key/cert/apiclient_cert.p12";
		//String password = "1358742202";
		
		//中医证书
		//String filePath = "d:/key/tcmkey/apiclient_cert.p12";
		//String password = "1357400202";

		InputStream is = null;
		
		/**
		 * 使用okhttp调用
		 */
		try{
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			is = new FileInputStream(keyUrl);
			keyStore.load(is, password.toCharArray());
			KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			kmf.init(keyStore, password.toCharArray());
			
			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(kmf.getKeyManagers(), null, null);
			OkHttpClient client = new OkHttpClient.Builder()
					.sslSocketFactory(sslContext.getSocketFactory(),new MyX509TrustManager()).build();
			RequestBody requestBody = RequestBody.create(mediaType, xml.getBytes("UTF-8"));
			Request request = new Request.Builder().url(url).post(requestBody).build();
			Response response = client.newCall(request).execute();
			if (response.isSuccessful()) {
				result = response.body().string();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				is = null;
			}
		}
		return result;
	}
	
}


